#pragma once
#include"common.hpp"
#include"Socket.hpp"
#include"Reactor.hpp"
// #include"Http.hpp"

// class Reactor;
using handler_t = std::function<void(int fd)>;
// using handler_t = std::function<std::string(std::string& str)>;

class connection{
public:
    connection(){}
    virtual void Recv() = 0;
    virtual void Send() = 0;
    virtual void Abnormal() = 0;
    virtual int Getfd() = 0;
    virtual uint32_t Getevents() = 0;
    virtual void Setevents(uint32_t events) = 0;
    void SetReactor(IReactor* rc){_own = rc;}
    void SetReactor(std::shared_ptr<IReactor> rc) { _own = rc.get(); }
    
    IReactor* GetReactor(){return _own;}

    void SetHandler(handler_t handler){_handler = handler;}
    handler_t GetHandler(){ return _handler;}

    ~connection(){}
private:
    handler_t _handler;

    IReactor* _own;
};


class normalconnection: public connection{
public:
    normalconnection(int fd,uint32_t events):_fd(fd),_events(events){
        SetNoBlock(_fd);
    }


    uint32_t Getevents()override{return _events;}
    void Setevents(uint32_t events)override{
        _events = events;
    }

    void Recv()override{
        LOG(level::DEBUG)<<"Recv normal conn";
        // GetHandler()(_fd); http
        //version 1 ET模式得循环读
        while(1)
        {
            char buff[1024];
            int n = recv(_fd,buff,sizeof(buff)-1,0);
            if(n > 0){
                buff[n] = 0;
                _inbuff += buff;
            }
            else if(n == 0){
                LOG(level::DEBUG)<<"client close";
                break;
            }
            else{
                if(errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                if(errno == EINTR)
                    continue;
                else{
                    Abnormal();
                    return;
                }
            }
        }

        if(!_inbuff.empty())
            // _outbuff += _handler(_inbuff);  我实现的是http 这个懂意思就行 由上层删除一条信息
            //using test = std::fun....<std::string(std::string&)>;
            _outbuff += _inbuff;  //test
        if(!_outbuff.empty())
            Send();

    }
    void Send()override{
        while(1){
            ssize_t size = send(_fd,_outbuff.c_str(),_outbuff.size(),0);
            if(size > 0){
                _outbuff.erase(0,size);
                if(_outbuff.empty())
                    break;
            }
            else if(size == 0){
                break;
            }else{
                if(errno == EAGAIN)
                    break;
                if(errno == EINTR)
                    continue;
                else{
                    Abnormal();
                    return;
                }
            }
        }
        //开启写事件关心
        if(!_outbuff.empty()){
            GetReactor()->OpenReadAndWrite(_fd,true,true);
        }
        else{
            GetReactor()->OpenReadAndWrite(_fd,true,false);
        }

    }

    void Abnormal()override{
        GetReactor()->Delconnection(_fd);
    }


    int Getfd()override{
        return _fd;
    }


    ~normalconnection(){}

private:
    int _fd;
    uint32_t _events;

    std::string _inbuff;
    std::string _outbuff;
};  


class listener:public connection{
public:
        
    listener(int port):_listensock(std::make_shared<TcpSocket>(port))
    {
        _listensock->BuideTcpSocket(port);
        _events = EPOLLIN | EPOLLET;
        SetNoBlock(_listensock->Getfd());
    }

    int Getfd()override{
        return _listensock->Getfd();
    }
    uint32_t Getevents()override{return _events;}
    void Setevents(uint32_t events) override{
        _events = events;
    }

    void BuideConnection(int fd){
        std::shared_ptr<connection> con = std::make_shared<normalconnection>(fd,_events);
        con->SetHandler(GetHandler());
        GetReactor()->Addconnection(con);
        
    }

    void Recv()override{
        LOG(level::DEBUG)<<"listener Recv";
        Inetaddr addr;
        int fd = _listensock->Accept(&addr);
        if(fd < 0){
            LOG(level::WARING)<<"accept error";
            exit(ACCEPT_ERR);
        }
        BuideConnection(fd);

    }


    void Send()override{}
    void Abnormal()override{}

    ~listener(){}
    
private:
    std::shared_ptr<Socket> _listensock;
    uint32_t _events;
};

